import sys
sys.path.append('/home/zhineng/simulatmarket/')

from module.common import Config
from module.common.common import summerTime
import pika
import pymysql
import redis
from DBUtils.PooledDB import PooledDB
from module.data.strategy import shortRunStrategy,update_to_mysql

import json,re
import time
import datetime
import pytz
import traceback
import redis
from module.data.strategy import shortRunStrategy

from module.const.Constant import const
from module.utils import TaskAdminUtil

import logging
log = logging.getLogger("handlelog")

# 连接mysql
def conn_mysql(db=Config.sql_db):
    connection = pymysql.connect(host=Config.sql_host, user=Config.sql_user, password=Config.sql_pass, db=db,
                                 port=Config.sql_port)
    return connection

# 连接redis
def conn_redis(db=0):
    r = redis.Redis(host=Config.redis_ip, password=Config.redis_auth, decode_responses=True,db=db)
    return r


class SimulaterMonitor(object):
    def __init__(self, queue, shortList,TrdEnv='SIMULATE'):
        credentials = pika.PlainCredentials(Config.rabbitmq_user, Config.rabbitmq_passwd)
        self.connection = pika.BlockingConnection(pika.ConnectionParameters(
            host=Config.rabbitmq_host, port=Config.rabbitmq_port, credentials=credentials))

        self.channel = self.connection.channel()
        # 消息队列
        self.queuename = queue

        self.TrdEnv = TrdEnv
        self.tbl_short_option = 'tbl_short_option_r' if self.TrdEnv=='REAL' else 'tbl_short_option_s'
        self.tbl_short_option_log = 'tbl_short_option_log_tr' if self.TrdEnv=='REAL' else 'tbl_short_option_log_ts'
        self.shortOptionDetail = 'shortOptionDetail_r' if self.TrdEnv=='REAL' else 'shortOptionDetail_s'
        self.shortPosition = 'shortPosition_r' if self.TrdEnv=='REAL' else 'shortPosition_s'
        self.conn = conn_mysql()
        self.cur = self.conn.cursor()
        self.r = conn_redis()
        self.shortList = shortList
        self.cache_data = {}

        self.trade_date_list = self.r.lrange('request_trading_days', 0, -1)
        self.trade_date_list_hk = self.r.lrange('request_trading_days_hk', 0, -1)


        # 初始化 清空持仓队列
        shortPosition = 'shortPosition_r' if self.TrdEnv == 'REAL' else 'shortPosition_s'
        r = redis.Redis(host='127.0.0.1', password=Config.redis_local_auth, decode_responses=True)
        r.hdel(shortPosition, f'{shortList[0][1]}&&&{shortList[0][2]}')
        r.close()

        cur = self.conn.cursor()
        O_name = shortList[0][1]
        acc_id = shortList[0][2]
        # 清空表
        cur.execute(f"update  {self.tbl_short_option}  set runState='运行中',order_status='未下单',continue_num=0,pnl=0,order_status_2='待买入条件达成' where O_name='{O_name}' and acc_id='{acc_id}'")

        # 清空交易明细
        cur.execute(f'delete from tbl_trade_detail_t where remark="{O_name}&&&{acc_id}"')

        # 删除日志
        cur.execute(f"delete from {self.tbl_short_option_log} where O_name='{O_name}' and acc_id='{acc_id}'")
        self.conn.commit()
        cur.close()

        self.code_name = {}


    ''' 实现回调函数来处理消息队列中的消息 '''
    def callback(self, ch, method, properties, body):
        ch.basic_ack(delivery_tag=method.delivery_tag)
        dataRaw = json.loads(body.decode())
        taskid = dataRaw['taskid']
        log.info("%s任务 模拟实盘逐笔：%s" % (taskid, dataRaw))
        try:
            data = dataRaw['item']
            code = data['code']

            summer_ed,summer_ed = summerTime(data['data_date'])
            if_summer = True if summer_ed < data['data_date'] < summer_ed else False
            trade_date_list = self.trade_date_list if 'US.' in code else self.trade_date_list_hk


            self.cache_data[code] = data  # 多个股的缓存数据更新
            self.code_name[code]=dataRaw['stock_name']


            shortRunStrategy(data, self.TrdEnv, if_summer, 100,
                                       self.tbl_short_option, self.cache_data,
                                       self.code_name, self.shortPosition,
                                       self.shortOptionDetail, self.tbl_short_option_log,
                                       log,
                                       trade_date_list, self.conn, self.r,
                                       shortList=self.shortList,
                                       optionDetailTmp='',
                                       shortPositionTmp='', ifTest=True,taskid=taskid)

        except TypeError as err:
            log.error("type error msg: %s, data: %s" % (err, dataRaw))
            traceback.print_exc()
        except KeyError as err:
            log.error("key error msg: %s, data: %s" % (err, dataRaw))
            traceback.print_exc()
        except SyntaxError as err:
            log.error("syntax error msg: %s, data: %s" % (err, dataRaw))
            traceback.print_exc()
        finally:
            self.shutdownHandle(taskid)

    ''' 初始化程序 '''
    def start(self):
        # 声明消息队列，消息将在这个队列传递，如不存在，则创建
        self.channel.queue_declare(queue=self.queuename, durable=False)

        # rabbitmq，用callback来接收消息
        self.channel.basic_consume(self.queuename, self.callback)
        # 开始接收信息，并进入阻塞状态，队列里有信息才会调用callback进行处理
        self.channel.start_consuming()

    def shutdownHandle(self, taskid):
        taskCenter = TaskAdminUtil.pullTaskCenter(taskid)
        # 任务手动暂停判断
        if taskCenter[1] == const.TASK_STATUS_STOP:
            log.info("%s任务 SimulaterMonitor触发手动暂停 详情信息：%s" % (taskid, taskCenter))
            for minitask in taskCenter[2]:
                if minitask[4] == const.TASK_STATUS_LOADING or minitask[4] == const.TASK_STATUS_RUNNING:
                    minitask[4] = const.TASK_STATUS_STOP
            self.connection.close()

        # 异常终止判断
        if taskCenter[1] == const.TASK_STATUS_EXCEPT:
            log.info("%s任务 SimulaterMonitor触发异常终止 详情信息：%s" % (taskid, taskCenter))
            for minitask in taskCenter[2]:
                if minitask[4] == const.TASK_STATUS_LOADING or minitask[4] == const.TASK_STATUS_RUNNING:
                    minitask[4] = const.TASK_STATUS_EXCEPT
            self.connection.close()

        # 完成结束判断
        if taskCenter[1] == const.TASK_STATUS_DONE:
            log.info("%s任务 SimulaterMonitor触发完成结束 详情信息：%s" % (taskid, taskCenter))
            self.connection.close()



if __name__ == '__main__':
    queuename = "US.AAPL"
    shortList = [('US.AAPL', '苹果模拟', '15858793')]
    realMonitor = SimulaterMonitor(queue=queuename, shortList=shortList)
    realMonitor.start()